﻿using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using Inkubator.Wizard.WebWizard.WizardControl;
using System.Text.RegularExpressions;

namespace Inkubator.Wizard.WebWizard.WizardUtilities
{
    public class CompileExpression
    {
        private string expression;
        private WizardWeb wizard;
        private int active;

        private Regex tokenizer;
        private int index = 0;

        public CompileExpression(string expression, WizardWeb wizard, int active)
        {
            this.expression = expression;
            this.wizard = wizard;
            this.active = active;
            this.tokenizer = new Regex(@"([\(\)\=\/\+\*])");
        }

        /// <summary>
        /// This method return a string array that contain the expression divided in each
        /// token, variable and regular expression.
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private string[] Tokenize(string expression)
        {
            expression = expression.Replace(" OR ", "+");
            expression = expression.Replace(" AND ", "*");
            expression = expression.Replace(" XOR ", "-");
            string[] array = tokenizer.Split(expression);

            List<string> tokens = new List<string>();

            foreach (string s in array)
            {
                if (!s.Equals("") && !s.Equals(" "))
                {
                    tokens.Add(s.Trim());
                }
            }

            return tokens.ToArray();
        }

        /// <summary>
        /// This method call the Tokenize method and return its result to the
        /// ParseExpression method to obtain the boolean value that represent if
        /// the option is correct or not.
        /// </summary>
        /// <returns></returns>
        public bool compile()
        {
            return this.parseExpression(this.Tokenize(expression));
        }

        private bool parseExpression( string[] expression )
        {
            bool value = true;
            bool evaluate = true;

            if (expression[index] == "(")
            {
                ++index;
                value = this.parseExpression(expression);
                evaluate = false;
            }
            
            if (evaluate)
            {
                string exp = this.obtainControlValue(expression[index]);
                index = index + 2;

                string reg = "";
                if (expression[index] == "/")
                {
                    index++;
                    while (expression[index] != "/")
                    {
                        reg += expression[index];
                        index++;
                    }
                }
                index++;

                Regex regex = new Regex(reg);
                value = regex.IsMatch(exp);
            }

            if (index >= expression.Length)
            {
                return value;
            }

            switch (expression[index])
            {
                case("+"):
                    ++index;
                    return (value | this.parseExpression(expression));
                case("*"):
                    ++index;
                    return (value & this.parseExpression(expression));
                case("-"):
                    ++index;
                    return (value ^ this.parseExpression(expression));
                case(")"):
                    ++index;
                    return (value);
                default:
                    return false;
            }
        }

        private string obtainControlValue(string exp)
        {
            StepWizard step = wizard.getSteps().ElementAt(active);

            WebControl control = step.obtainControl(exp);
            return ((TextBox)control).Text;
        }

    }
}
